package com.framework.common.mongodb.utils;

import com.framework.common.mongodb.entity.QueryEntity;
import com.framework.common.mongodb.em.QueryModel;
import com.framework.common.mongodb.em.QueryOperator;
import com.framework.common.mongodb.builder.QueryBuilder;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.*;


/**
 * \* Created with IntelliJ IDEA.
 * \* User: ywb
 * \* Date: 2021/11/19
 * \* Time: 13:57
 * \* Description:
 * \
 */
public class MongoQueryUtil {

    /**
     * 构建查询实体
     * @param field
     * @param value
     * @param operators
     * @return
     */
    public static QueryEntity buildQueryEntity(String field, Object[] value, QueryOperator[] operators) {
        QueryEntity entity = new QueryEntity();
        entity.setField(field);
        entity.setValue(value);
        entity.setType(operators);
        return entity;
    }

    /**
     * 构建查询实体
     * @param field
     * @param value
     * @param operator
     * @return
     */
    public static QueryEntity buildQueryEntity(String field, Object[] value, QueryOperator operator) {
        QueryEntity entity = new QueryEntity();
        entity.setField(field);
        entity.setValue(value);
        entity.setType(new QueryOperator[]{operator});
        return entity;
    }

    /**
     * 构建查询实体 支持 =,>,<,>=,<=,regex
     * @param field
     * @param value
     * @param operator
     * @return
     */
    public static QueryEntity buildQueryEntity(String field, Object value, QueryOperator operator) {
        QueryEntity entity = new QueryEntity();
        entity.setField(field);
        entity.setValue(new Object[]{value});
        entity.setType(new QueryOperator[]{operator});
        return entity;
    }

    /**
     * 构建单语句查询：等于 =
     * @param field 查询字段名
     * @param value 查询值
     * @return
     */
    public static Map<String, QueryEntity> is(String field, Object value) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, value, QueryOperator.IS);
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：包含 in
     * @param field 查询字段名
     * @param values 查询数组值
     * @return
     */
    public static Map<String, QueryEntity> in(String field, Object... values) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, values, QueryOperator.IN);
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：不包含 nin
     * @param field 查询字段名
     * @param values 查询数组值
     * @return
     */
    public static Map<String, QueryEntity> nin(String field, Object... values) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, values, QueryOperator.NIN);
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：不等于 ne
     * @param field 查询字段名
     * @param value 查询值
     * @return
     */
    public static Map<String, QueryEntity> ne(String field, Object value) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, value, QueryOperator.NIN);
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：正则, 模糊查询 regex
     * @param field 查询字段名
     * @param value 查询值
     */
    public static Map<String, QueryEntity> regex(String field, Object value) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, value, QueryOperator.REGEX);
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：大于 >
     * @param field 查询字段名
     * @param value 查询值
     */
    public static Map<String, QueryEntity> gt(String field, Object value) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, new Object[]{value}, new QueryOperator[] {QueryOperator.GT});
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：小于 >
     * @param field 查询字段名
     * @param value 查询值
     */
    public static Map<String, QueryEntity> lt(String field, Object value) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, new Object[]{value}, new QueryOperator[] {QueryOperator.LT});
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：小于等于 <=
     * @param field 查询字段名
     * @param value 查询值
     */
    public static Map<String, QueryEntity> lte(String field, Object value) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, new Object[]{value}, new QueryOperator[] {QueryOperator.LTE});
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：大于等于 >=
     * @param field 查询字段名
     * @param value 查询值
     */
    public static Map<String, QueryEntity> gte(String field, Object value) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, new Object[]{value}, new QueryOperator[] {QueryOperator.GTE});
        map.put(field, entity);
        return map;
    }

    /**
     * 构建单语句查询：范围查询 大于等于 小于等于  即between and
     * @param field 查询字段名
     * @param smallValue 查询值 较小值
     * @param bigValue 查询值 较大值
     */
    @Deprecated
    public static Map<String, QueryEntity> between(String field, Object smallValue, Object bigValue) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        QueryEntity entity = buildQueryEntity(field, new Object[]{smallValue, bigValue}, new QueryOperator[] {QueryOperator.GTE, QueryOperator.LTE});
        map.put(field, entity);
        return map;
    }

    /**
     * 根据QueryEntity数组来构建查询Map
     * @param entities
     * @return
     */
    public static Map<String, QueryEntity> buildQueryMap(QueryEntity... entities) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        for (QueryEntity entity : entities) {
            String field = entity.getField();
            if (map.containsKey(field)) {
                QueryEntity entity1 = map.get(field);
                List<Object> valList = new ArrayList<>();
                valList.addAll(Arrays.asList(entity1.getValue()));
                valList.addAll(Arrays.asList(entity.getValue()));
                List<QueryOperator> typeList = new ArrayList<>();
                typeList.addAll(Arrays.asList(entity1.getType()));
                typeList.addAll(Arrays.asList(entity.getType()));
                map.put(field, buildQueryEntity(field, valList.toArray(), typeList.toArray(new QueryOperator[0])));
            } else {
                map.put(field, entity);
            }
        }
        return map;
    }

    /**
     * 构建复杂联合查询语句
     * @param entities 单句查询集合
     * @param queryModel 查询关联关系
     * @return
     */
    public static Query buildQuery(QueryEntity[] entities, QueryModel queryModel) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        for (QueryEntity entity : entities) {
            map.put(entity.getField(), entity);
        }
        QueryBuilder builder = new QueryBuilder(map, queryModel);
        return new Query(builder.queryCriteria());
    }

    /**
     * 构建复杂联合查询语句AND
     * @param fields  查询字段名集合
     * @param values  字段值对应相关查询条件值
     * @param operators 字段值与查询值的关系 支持 =,>,>=,<,<=,in
     * @return
     */
    public static Query buildAndQuery(String[] fields, Object[][] values, QueryOperator[] operators) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        for (int i = 0; i < fields.length; i++) {
            QueryEntity entity = buildQueryEntity(fields[i], values[i], operators[i]);
            map.put(fields[i], entity);
        }
        QueryBuilder builder = new QueryBuilder(map, QueryModel.AND);
        return new Query(builder.queryCriteria());
    }

    /**
     * 构建复杂联合查询语句AND
     * @param entities 单句查询集合
     * @return
     */
    public static Query buildAndQuery(QueryEntity... entities) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        for (QueryEntity entity : entities) {
            map.put(entity.getField(), entity);
        }
        QueryBuilder builder = new QueryBuilder(map, QueryModel.AND);
        return new Query(builder.queryCriteria());
    }

    /**
     * 构建复杂联合查询语句OR
     * @param fields  查询字段名集合
     * @param values  字段值对应相关查询条件值
     * @param operators 字段值与查询值的关系 支持 =,>,>=,<,<=,in
     * @return
     */
    public static Query buildOrQuery(String[] fields, Object[][] values, QueryOperator[] operators) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        for (int i = 0; i < fields.length; i++) {
            QueryEntity entity = buildQueryEntity(fields[i], values[i], operators[i]);
            map.put(fields[i], entity);
        }
        QueryBuilder builder = new QueryBuilder(map, QueryModel.OR);
        return new Query(builder.queryCriteria());
    }

    /**
     * 构建复杂联合查询语句OR
     * @param entities 单句查询集合
     * @return
     */
    public static Query buildOrQuery(QueryEntity... entities) {
        Map<String, QueryEntity> map = new HashMap<String, QueryEntity>();
        for (QueryEntity entity : entities) {
            map.put(entity.getField(), entity);
        }
        QueryBuilder builder = new QueryBuilder(map, QueryModel.OR);
        return new Query(builder.queryCriteria());
    }

    /**
     * 构造查询语句 !=
     */
    public static Query qne(String field, Object value) {
        Criteria criteria = Criteria.where(field).ne(value);
        return Query.query(criteria);
    }

    /**
     * 构造查询语句 not in
     */
    public static Query qnin(String field, Object... values) {
        Criteria criteria = Criteria.where(field).nin(values);
        return Query.query(criteria);
    }

    /**
     * 构造查询语句 in
     */
    public static Query qin(String field, Object... values) {
        Criteria criteria = Criteria.where(field).in(values);
        return Query.query(criteria);
    }

    /**
     * 构造查询语句 is not null
     *
     */
    public static Query notNull(String field) {
        Criteria criteria = Criteria.where(field).not();
        return Query.query(criteria);
    }


}
